//===============================================================================
// Microsoft patterns & practices Enterprise Library Contribution
// Resource Application Block
//===============================================================================

using System;
using System.Diagnostics;
using System.IO;
using System.Resources;
using System.Globalization;
using System.Drawing;
using System.Collections;
using EntLibContrib.Resource.Configuration;
using EntLibContrib.Resource.Managers;

#if !NUNIT
using Microsoft.VisualStudio.TestTools.UnitTesting;
#else
using NUnit.Framework;
using TestClass = NUnit.Framework.TestFixtureAttribute;
using ClassInitialize = NUnit.Framework.TestFixtureSetUpAttribute;
using TestInitialize = NUnit.Framework.SetUpAttribute;
using TestCleanup = NUnit.Framework.TearDownAttribute;
using TestMethod = NUnit.Framework.TestAttribute;
#endif

namespace EntLibContrib.Resource.Tests
{
	[TestClass]
	public class BinaryResourceWriterFixture
	{
		private static ResourceManagerFactory factory;
		private static ResourceManager resourceManager;
		private static string pathName;
		private static string baseName;
		private static string originalBaseName;
		private static string neutralFileName;
		private static string frenchFileName;
		private static string germanFileName;

		[ClassInitialize]
#if NUNIT
		public void Initialize()
#else
		public static void Initialize(TestContext context)
#endif
		{
			string fileName;
			FileInfo fileInfo;
			pathName = ".";
			originalBaseName = "Resources";
			baseName = "Test";
			fileName = ResourceFileName.Build(pathName, originalBaseName, CultureInfo.InvariantCulture, ResourceManagerSettings.BinaryExtension);
			neutralFileName = ResourceFileName.Build(pathName, baseName, CultureInfo.InvariantCulture, ResourceManagerSettings.BinaryExtension);
			fileInfo = new FileInfo(fileName);
			fileInfo.CopyTo(neutralFileName, true);
			fileName = ResourceFileName.Build(pathName, originalBaseName, new CultureInfo("fr"), ResourceManagerSettings.BinaryExtension);
			frenchFileName = ResourceFileName.Build(pathName, baseName, new CultureInfo("fr"), ResourceManagerSettings.BinaryExtension);
			fileInfo = new FileInfo(fileName);
			fileInfo.CopyTo(frenchFileName, true);
			fileName = ResourceFileName.Build(pathName, originalBaseName, new CultureInfo("de"), ResourceManagerSettings.BinaryExtension);
			germanFileName = ResourceFileName.Build(pathName, baseName, new CultureInfo("de"), ResourceManagerSettings.BinaryExtension);
			fileInfo = new FileInfo(fileName);
			fileInfo.CopyTo(germanFileName, true);
			factory = new ResourceManagerFactory(TestConfigurationSource.GenerateConfiguration());
			resourceManager = factory.Create("AssemblyResourceManager");
		}

		[TestCleanup]
		public void DeleteResource()
		{
		}

		[TestMethod]
		public void CreateBinaryResourceWriter()
		{
			BinaryResourceWriter binaryResourceWriter = new BinaryResourceWriter(neutralFileName);
			Assert.IsNotNull(binaryResourceWriter);
			binaryResourceWriter.Close();
		}

		[TestMethod]
		[ExpectedException(typeof(ArgumentNullException))]
		public void CreateBinaryResourceWriterWithNullFileName()
		{
			BinaryResourceWriter binaryResourceWriter = new BinaryResourceWriter((Stream)null);
			Assert.Fail();
		}

		[TestMethod]
		[ExpectedException(typeof(ArgumentNullException))]
		public void CreateBinaryResourceWriterWithEmptyFileName()
		{
			BinaryResourceWriter binaryResourceWriter = new BinaryResourceWriter(String.Empty);
			Assert.Fail();
		}

		[TestMethod]
		public void AddNeutralString ()
		{
			resourceManager.CultureInfo = CultureInfo.InvariantCulture;
			BinaryResourceWriter binaryResourceWriter = new BinaryResourceWriter(neutralFileName);
			binaryResourceWriter.AddResource("Ewdev", resourceManager["Ewdev"]);
			binaryResourceWriter.Close();
			BinaryResourceSet resourceSet = new BinaryResourceSet(pathName, baseName, resourceManager.CultureInfo);
			Assert.AreEqual(1, resourceSet.Count);
		}

		[TestMethod]
		public void AddNeutralInteger ()
		{
			resourceManager.CultureInfo = CultureInfo.InvariantCulture;
			BinaryResourceWriter binaryResourceWriter = new BinaryResourceWriter(neutralFileName);
			binaryResourceWriter.AddResource("TestInteger", resourceManager["TestInteger", typeof(System.Int32)]);
			binaryResourceWriter.Close();
			BinaryResourceSet resourceSet = new BinaryResourceSet(pathName, baseName, resourceManager.CultureInfo);
			Assert.AreEqual(1, resourceSet.Count);
		}

		[TestMethod]
		public void AddNeutralIcon ()
		{
			resourceManager.CultureInfo = CultureInfo.InvariantCulture;
			BinaryResourceWriter binaryResourceWriter = new BinaryResourceWriter(neutralFileName);
			binaryResourceWriter.AddResource("TestIcon", resourceManager["TestIcon", typeof(Icon)]);
			binaryResourceWriter.Close();
			BinaryResourceSet resourceSet = new BinaryResourceSet(pathName, baseName, resourceManager.CultureInfo);
			Assert.AreEqual(1, resourceSet.Count);
		}

		[TestMethod]
		public void AddNeutralImage ()
		{
			resourceManager.CultureInfo = CultureInfo.InvariantCulture;
			BinaryResourceWriter binaryResourceWriter = new BinaryResourceWriter(neutralFileName);
			binaryResourceWriter.AddResource("TestImage", resourceManager["TestImage", typeof(Bitmap)]);
			binaryResourceWriter.Close();

			BinaryResourceReader binaryResourceReader = new BinaryResourceReader(pathName, baseName, resourceManager.CultureInfo);
			object actual = null;
			foreach (DictionaryEntry dictionaryEntry in binaryResourceReader)
			{
				if (dictionaryEntry.Key.ToString() == "TestImage")
				{
					actual = dictionaryEntry.Value;
					break;
				}
			}
#if NUNIT
			Assert.IsInstanceOfType(typeof(Bitmap), actual);
#else
			Assert.IsInstanceOfType(actual, typeof(Bitmap));
#endif
		}

		[TestMethod]
		public void AddNeutralAudio ()
		{
			resourceManager.CultureInfo = CultureInfo.InvariantCulture;
			BinaryResourceWriter binaryResourceWriter = new BinaryResourceWriter(neutralFileName);
			UnmanagedMemoryStream ums = (UnmanagedMemoryStream)resourceManager["TestSound", typeof(UnmanagedMemoryStream)];
			byte[] buffer = new byte[ums.Length];
			ums.Read(buffer, 0 ,(int)ums.Length);
			binaryResourceWriter.AddResource("TestSound", buffer);
			binaryResourceWriter.Close();
			BinaryResourceSet resourceSet = new BinaryResourceSet(pathName, baseName, resourceManager.CultureInfo);
			Assert.AreEqual(1, resourceSet.Count);
		}

		[TestMethod]
		public void AddNeutralColour ()
		{
			resourceManager.CultureInfo = CultureInfo.InvariantCulture;
			BinaryResourceWriter binaryResourceWriter = new BinaryResourceWriter(neutralFileName);
			binaryResourceWriter.AddResource("TestColour", resourceManager["TestColour", typeof(Color)]);
			binaryResourceWriter.Close();
			BinaryResourceSet resourceSet = new BinaryResourceSet(pathName, baseName, resourceManager.CultureInfo);
			Assert.AreEqual(1, resourceSet.Count);
		}

		[TestMethod]
		public void AddNeutralByteArray()
		{
			resourceManager.CultureInfo = CultureInfo.InvariantCulture;
			BinaryResourceWriter binaryResourceWriter = new BinaryResourceWriter(neutralFileName);
			byte[] byteArray = SerializationUtility.ToBytes(resourceManager["TestImage", typeof(Bitmap)]);
			binaryResourceWriter.AddResource("TestByteArray", byteArray);
			binaryResourceWriter.Close();
			BinaryResourceSet resourceSet = new BinaryResourceSet(pathName, baseName, resourceManager.CultureInfo);
			Assert.AreEqual(1, resourceSet.Count);
		}

		[TestMethod]
		public void AddFrenchString ()
		{
			resourceManager.CultureInfo = new CultureInfo("fr");
			BinaryResourceWriter binaryResourceWriter = new BinaryResourceWriter(frenchFileName);
			binaryResourceWriter.AddResource("TestString", resourceManager["TestString"]);
			binaryResourceWriter.Close();
			BinaryResourceSet resourceSet = new BinaryResourceSet(pathName, baseName, resourceManager.CultureInfo);
			Assert.AreEqual(1, resourceSet.Count);
		}

		[TestMethod]
		public void AddFrenchInteger ()
		{
			resourceManager.CultureInfo = new CultureInfo("fr");
			BinaryResourceWriter binaryResourceWriter = new BinaryResourceWriter(frenchFileName);
			binaryResourceWriter.AddResource("TestInteger", resourceManager["TestInteger", typeof(System.Int32)]);
			binaryResourceWriter.Close();
			BinaryResourceSet resourceSet = new BinaryResourceSet(pathName, baseName, resourceManager.CultureInfo);
			Assert.AreEqual(1, resourceSet.Count);
		}

		[TestMethod]
		public void AddFrenchImage ()
		{
			resourceManager.CultureInfo = new CultureInfo("fr");
			BinaryResourceWriter binaryResourceWriter = new BinaryResourceWriter(frenchFileName);
			binaryResourceWriter.AddResource("TestImage", resourceManager["TestImage", typeof(Bitmap)]);
			binaryResourceWriter.Close();
			BinaryResourceSet resourceSet = new BinaryResourceSet(pathName, baseName, resourceManager.CultureInfo);
			Assert.AreEqual(1, resourceSet.Count);
		}

		[TestMethod]
		public void AddGermanString ()
		{
			resourceManager.CultureInfo = new CultureInfo("de");
			BinaryResourceWriter binaryResourceWriter = new BinaryResourceWriter(germanFileName);
			binaryResourceWriter.AddResource("TestString", resourceManager["TestString"]);
			binaryResourceWriter.Close();
			BinaryResourceSet resourceSet = new BinaryResourceSet(pathName, baseName, resourceManager.CultureInfo);
			Assert.AreEqual(1, resourceSet.Count);
		}

		[TestMethod]
		public void AddGermanInteger ()
		{
			resourceManager.CultureInfo = new CultureInfo("de");
			BinaryResourceWriter binaryResourceWriter = new BinaryResourceWriter(germanFileName);
			binaryResourceWriter.AddResource("TestInteger", resourceManager["TestInteger", typeof(System.Int32)]);
			binaryResourceWriter.Close();
			BinaryResourceSet resourceSet = new BinaryResourceSet(pathName, baseName, resourceManager.CultureInfo);
			Assert.AreEqual(1, resourceSet.Count);
		}

		[TestMethod]
		public void AddGermanImage ()
		{
			resourceManager.CultureInfo = new CultureInfo("de");
			BinaryResourceWriter binaryResourceWriter = new BinaryResourceWriter(germanFileName);
			binaryResourceWriter.AddResource("TestImage", resourceManager["TestImage", typeof(Bitmap)]);
			binaryResourceWriter.Close();
			BinaryResourceSet resourceSet = new BinaryResourceSet(pathName, baseName, resourceManager.CultureInfo);
			Assert.AreEqual(1, resourceSet.Count);
		}

		[TestMethod]
		public void AddNeutralResourceDataNode()
		{
			resourceManager.CultureInfo = CultureInfo.InvariantCulture;
			string name = "TestDataNode";
			object value = "Test Data Node";
			string typeName = value.GetType().AssemblyQualifiedName;

			BinaryResourceWriter binaryResourceWriter = new BinaryResourceWriter(neutralFileName);
			ResourceDataNode writeDataNode = new ResourceDataNode(name, value);
			binaryResourceWriter.AddResource(name, writeDataNode);
			binaryResourceWriter.Close();

			BinaryResourceReader binaryResourceReader = new BinaryResourceReader(pathName, baseName, resourceManager.CultureInfo);
			binaryResourceReader.UseDataNodes = true;
			binaryResourceReader.GetEnumerator();
			string actualTypeName = "";
			object actualValue = String.Empty;
			IDictionaryEnumerator enumerator = binaryResourceReader.GetEnumerator();
			while (enumerator.MoveNext())
			{
				ResourceDataNode readDataNode = (ResourceDataNode)enumerator.Value;
				if (readDataNode.Name == name)
				{
					actualTypeName = readDataNode.TypeName;
					actualValue = readDataNode.Value;
					break;
				}
			}
			Debug.WriteLine(name + ": type = " + actualTypeName + " value = " + actualValue);
			Assert.AreEqual(typeName, actualTypeName);
			Assert.AreEqual(value.ToString(), actualValue.ToString());
		}

		[TestMethod]
		public void AddNeutralStringWithComment()
		{
			resourceManager.CultureInfo = CultureInfo.InvariantCulture;
			string name = "Ewdev";
			object value = resourceManager[name];
			string typeName = value.GetType().AssemblyQualifiedName;
			string comment = "This is a Test";

			BinaryResourceWriter binaryResourceWriter = new BinaryResourceWriter(neutralFileName);
			ResourceDataNode writeDataNode = new ResourceDataNode(name, value);
			writeDataNode.Comment = comment;
			binaryResourceWriter.AddResource(name, writeDataNode);
			binaryResourceWriter.Close();

			BinaryResourceReader binaryResourceReader = new BinaryResourceReader(pathName, baseName, resourceManager.CultureInfo);
			binaryResourceReader.UseDataNodes = true;
			binaryResourceReader.GetEnumerator();
			string actualComment = "";
			string actualTypeName = "";
			object actualValue = String.Empty;
			IDictionaryEnumerator enumerator = binaryResourceReader.GetEnumerator();
			while (enumerator.MoveNext())
			{
				ResourceDataNode readDataNode = (ResourceDataNode)enumerator.Value;
				if (readDataNode.Name == name)
				{
					actualComment = readDataNode.Comment;
					actualTypeName = readDataNode.TypeName;
					actualValue = readDataNode.Value;
					break;
				}
			}
			Debug.WriteLine(name + ": type = " + actualTypeName + " value = " + actualValue + " comment = " + actualComment);
			Assert.AreEqual(typeName, actualTypeName);
			Assert.AreEqual(value.ToString(), actualValue.ToString());
			Assert.IsNull(actualComment, "Binary resources do not support comments");
		}

		[TestMethod]
		public void AddNeutralFileRef()
		{
			resourceManager.CultureInfo = CultureInfo.InvariantCulture;
			string name = "TestFileRef";
			string fileName = "test.bmp";
			string fileType = typeof(Bitmap).AssemblyQualifiedName;
			ResourceFileRef resourceFileRef = new ResourceFileRef(fileName, fileType);

			BinaryResourceWriter binaryResourceWriter = new BinaryResourceWriter(neutralFileName);
			ResourceDataNode writeDataNode = new ResourceDataNode(name, resourceFileRef);
			binaryResourceWriter.AddResource(name, writeDataNode);
			binaryResourceWriter.Close();

			BinaryResourceReader binaryResourceReader = new BinaryResourceReader(pathName, baseName, resourceManager.CultureInfo);
			binaryResourceReader.UseDataNodes = true;
			ResourceDataNode readDataNode = null;
			IDictionaryEnumerator enumerator = binaryResourceReader.GetEnumerator();
			while (enumerator.MoveNext())
			{
				readDataNode = (ResourceDataNode)enumerator.Value;
				if (readDataNode.Name == name)
					break;
			}
			Debug.WriteLine(name + ": type = " + readDataNode.TypeName + " value = " + readDataNode.Value.ToString());
			Assert.IsNull(readDataNode.FileRef, "Binary resources do not support file refs");
#if NUNIT
			Assert.IsInstanceOfType(typeof(byte[]), readDataNode.Value, "files from refs are embedded as byte arrays");
#else
			Assert.IsInstanceOfType(readDataNode.Value, typeof(byte[]), "files from refs are embedded as byte arrays");
#endif
			Assert.AreEqual(readDataNode.TypeName, typeof(byte[]).AssemblyQualifiedName, "files from refs are embedded as byte arrays");
		}
	}
}
